﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WWDemon.Core.WebSocket;
using WWDemon.Log;
using WWDemon.Model;
using WWDemon.Core;
using Newtonsoft.Json.Linq;

namespace WWDemon.WebServer
{
    public class AccountServer
    {
        private static readonly object objLock = new object();
        private static AccountServer  server;

        public static AccountServer Instance
        {
            get
            {
                if (server == null)
                    lock (objLock)
                    {
                        if (server == null) server = new AccountServer();
                    }
                return server;
            }
        }

        private int prot = 54321;
        private string ip = "127.0.0.1";

        private WebSocketServer webSocket;
        public AccountServer()
        {
            //发送给PC的消息都走 二进制 压缩模式，精简数据大小，优化传输速度 与 带宽压力

            //发送给WEB的消息 都走json字符串 格式，js无法处理二进制数据


            webSocket = new WebSocketServer(ip,prot);
            webSocket.OnAccept += WebSocket_OnAccept;
            webSocket.OnClose += WebSocket_OnClose;
            webSocket.OnReceivePC += WebSocket_OnReceivePC;
            webSocket.OnReceiveWeb += WebSocket_OnReceiveWeb;
        }

        public Dictionary<string, string> WebClient = new Dictionary<string, string>();
        public Dictionary<string, PCClientInfo> PCClient = new Dictionary<string, PCClientInfo>();


        private void WebSocket_OnReceiveWeb(string ipProt, Model.CommondWeb receiveData)
        {
            switch (receiveData.Key)
            {
                case Model.CommondKey.Login:

                    if(!WebClient.ContainsKey(ipProt))
                    {
                        WebClient.Add(ipProt, ipProt);
                    }

                    break;
                case Model.CommondKey.GetOrderInfo:


                    //发送消息给PC客户端

                    GetOrderInfo getOrder = receiveData.Data.ToObject<GetOrderInfo>();

                    if(!PCClient.TryGetValue(getOrder.IpProt,out var client))
                    {
                        CommondWeb commond = new CommondWeb();
                        commond.Key = CommondKey.Message;
                        commond.Data["ErrorMsg"] = "这个IP的PC客户端已掉线";
                        SendData(commond.ToJson(), ipProt);
                        return;
                    }

                    // 这里 服务器收到 控制消息 就是web 界面的消息，  给某个PC客户端 发消息

                    //CommondKey.GetOrderInfo 是命令
                    //getOrder 是服务器发什么内容给PC 客户端， 

                    //getOrder.IpProt  是发给哪个PC 客户端


                    SendData(CommondKey.GetOrderInfo, getOrder, getOrder.IpProt);

                    break;

            }
        }

        private void WebSocket_OnReceivePC(string ipProt, Model.CommondPC receiveData)
        {
            switch(receiveData.Key)
            {
                case Model.CommondKey.Login:
                    {
                        if (!PCClient.TryGetValue(ipProt, out var client))
                        {
                            client = new PCClientInfo();
                            client.Id = ipProt;
                            PCClient.Add(client.Id, client);
                        }
                        var loginInfo = receiveData.Data.ToObjectByte<ClientLoginModel>();
                        client.Name = loginInfo.AccountName;
                        client.TestDateTime = DateTime.Now;

                        SendData(CommondKey.Login,"", ipProt);


                        CommondWeb commond = new CommondWeb();
                        commond.Key = CommondKey.Login;
                        commond.Data["Msg"] = "新用户登录";
                        commond.Data["Account"] = client.Name;
                        commond.Data["IpRrot"] = client.Id;

                        string value = commond.ToJson();

                        foreach (var item in WebClient)
                        {
                            SendData(value, item.Key);
                        }

                        LogHelper.Log(LogDefine.LogDebug, $"新用户登录:{ipProt}");
                    }


                    break;
                case Model.CommondKey.GetOrderInfo:
                    {
                        //收到PC客户端的 订单信息回复

                        if (!PCClient.TryGetValue(ipProt, out _))
                        {
                            MessageInfo message = new MessageInfo();
                            message.ErrorMes = "用户未登陆";
                            SendData(CommondKey.Message, message, ipProt);
                            return;
                        }

                        //转发给WEB界面
                        //PC发上来的是经过压缩后的 二进制消息，先转会原始对象，ToObjectByte，再转成命令能接受的JSON类型
                        // 后续还可以优化 省掉这个转换过程

                        CommondWeb commond = new CommondWeb();
                        commond.Key = CommondKey.Message;
                        commond.Data = receiveData.Data.ToObjectByte<SendOrderInfoModel>().ToJObject();
                        string value = commond.ToJson();

                        foreach (var item in WebClient)
                        {
                            SendData(value, item.Key);
                        }
                    }


                    break;
            }
        }

        private void WebSocket_OnClose(string ipProt)
        {
            LogHelper.Log(LogDefine.LogDebug, $"链接:{ipProt}关闭");

            WebClient.Remove(ipProt);
            PCClient.Remove(ipProt);

        }

        private void WebSocket_OnAccept(string ipProt)
        {
            LogHelper.Log(LogDefine.LogDebug, $"新链接:{ipProt}");
        }

        public void Strat()
        {
            webSocket.Start();
        }

        public void Stop()
        {

        }

        public void SendData(Enum mainCmd, string data, string ipProt)
        {
            webSocket.SendData(mainCmd, data, ipProt);
        }
        public void SendData(Enum mainCmd, byte[] data, string ipProt)
        {
            webSocket.SendData(mainCmd, data, ipProt);
        }

        public void SendData<T>(Enum mainCmd,T data, string ipProt)
        {
            webSocket.SendData(mainCmd,  data, ipProt);
        }

        public void SendData(string value, string ipProt)
        {
            webSocket.SendData(value, ipProt);
        }
    }
}
